package com.hue.concurrent.day03;

import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

/*
    保护性-暂停模式增强：多个线程等待多个线程的结果
 */
public class Demo06 {
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new People().start();
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        int count = 1;
        for (int id : MailBox.getIds()) {
            new Postman(id, "hello" + count++).start();
        }
    }

    public static class People extends Thread {
        @Override
        public void run() {
            GuardedObject mail = MailBox.createGuardedObject();
            System.out.println("开始等待id=" + mail.getId() + "的mail");
            Object res = mail.getResponse(3000);
            System.out.println("接收到id=" + mail.getId() + "的结果:" + res);
        }
    }

    public static class Postman extends Thread {
        private int id;
        private String res;

        public Postman(int id, String res) {
            this.id = id;
            this.res = res;
        }

        @Override
        public void run() {
            //将res投递给对应id的GuardedObject
            System.out.println("id=" + id + "的mail已经送到");
            GuardedObject guardedObject = MailBox.getGuardedObject(id);
            guardedObject.setResponse(res);
        }
    }

    public static class MailBox {
        private static int id = 0;
        //存储所有结果
        private static Map<Integer, GuardedObject> mails = new Hashtable<>();

        private synchronized static int getId() {
            return ++id;
        }

        public static GuardedObject createGuardedObject() {
            int id = getId();
            GuardedObject guardedObject = new GuardedObject(id);
            mails.put(id, guardedObject);
            return guardedObject;
        }

        public static GuardedObject getGuardedObject(int id) {
            //返回GuardedObject并删除
            return mails.remove(id);
        }

        public static Set<Integer> getIds() {
            return mails.keySet();
        }
    }

    /*
      关联两个线程的对象
    */
    public static class GuardedObject {
        private int id;
        private Object response;

        public GuardedObject(int id) {
            this.id = id;
        }

        public int getId() {
            return id;
        }

        public Object getResponse(long timeout) {
            synchronized (this) {
                //开始时间
                long start = System.currentTimeMillis();
                //已用时间
                long wait = 0;
                while (response == null) {
                    if (wait >= timeout) {  //等待超时
                        break;
                    }
                    try {
                        this.wait(timeout - wait);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    wait = System.currentTimeMillis() - start;
                }
            }
            return response;
        }

        public void setResponse(Object response) {
            synchronized (this) {
                this.response = response;
                this.notifyAll();
            }
        }
    }
}
